#include "structure.h"


structure::structure(void)
{
	position = vertex();
	radius = 0;
	type = SUPPLY;
	cost = COST_SUPPLY;
	team = RED;

	target = NULL;
	targetingAgent = false;
	atkTimer = 0;
}

structure::structure(TYPE t, vertex inpos, team_T iTeam)
{
	position = inpos;
	type = t;
	team = iTeam;
	target = NULL;
	targetingAgent = false;
	atkTimer = 0;

	switch (type)
	{
		case CITADEL:
			radius = 10;
			cost = COST_CITADEL;
			hp = MAX_HP_CITADEL;
			break;
		case SUPPLY:
			radius = 3;
			cost = COST_SUPPLY;
			hp = MAX_HP_SUPPLY;
			break;
		case TOWER:
			radius = 2;
			cost = COST_TOWER;
			hp = MAX_HP_TOWER;
			break;
	}
}


structure::~structure(void)
{
}


bool structure::occupy(Terrain *t)
{
	// Adjust world coordinates to center the structure
	// on the cell(s) that the user clicked on.
	int cellSize = ceil(2 * radius / (float)STEP);
	vertex center;

	if (0 == cellSize % 2)
	{ // Even
		center = Terrain::GetTerrainPoint(position + AVector(-STEP/2.0, -STEP/2.0));

		// Check that structure will lie within the world boundaries
		if (position.x - radius < -WIDTH / 2.0 || 
			position.y - radius < -HEIGHT / 2.0 || 
			position.x + radius > WIDTH / 2.0 || 
			position.y + radius > HEIGHT / 2.0)
		{
			// The structure doesn't fit.
			return false;
		}
		
		// Check for occupation conflicts
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{
				if (Terrain::OCCUPIED == t->GetTerrainType(center.y - (cellSize - 2)/2 + i,
														   center.x - (cellSize - 2)/2 + j))
				{
					return false;
				}
			}
		}
		
		// Occupy map cells
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{
				t->Occupy(center.y - (cellSize - 2)/2 + i,
						  center.x - (cellSize - 2)/2 + j);
			}
		}
	}
	else
	{ // Odd
		center = Terrain::GetTerrainPoint(position);  // center in cell coordinates

		// Check that structure will lie within the world boundaries
		if (position.x - radius < -WIDTH / 2.0 || 
			position.y - radius < -HEIGHT / 2.0 || 
			position.x + radius > WIDTH / 2.0 || 
			position.y + radius > HEIGHT / 2.0)
		{
			// The structure doesn't fit.
			return false;
		}
		
		// Check for occupation conflicts
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{
				if (Terrain::OCCUPIED == t->GetTerrainType(center.y - (cellSize - 1)/2 + i,
														   center.x - (cellSize - 1)/2 + j))
				{
					return false;
				}
			}
		}
		
		// Occupy map cells
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{

				t->Occupy(center.y - (cellSize - 1)/2 + i,
						  center.x - (cellSize - 1)/2 + j);
			}
		}
	}

	return true;
}

bool structure::occupy(Terrain *t, vertex p)
{
	// Adjust world coordinates to center the structure
	// on the cell(s) that the user clicked on.
	int cellSize = ceil(2 * radius / (float)STEP);
	vertex center;

	if (0 == cellSize % 2)
	{ // Even
		center = Terrain::GetTerrainPoint(p + AVector(-STEP/2.0, -STEP/2.0));

		// get center in world coordinates for rendering structure
		position = Terrain::GetWorldPoint(center.x, center.y) + AVector(STEP/2.0, STEP/2.0);

		// Check that structure will lie within the world boundaries
		if (position.x - radius < -WIDTH / 2.0 || 
			position.y - radius < -HEIGHT / 2.0 || 
			position.x + radius > WIDTH / 2.0 || 
			position.y + radius > HEIGHT / 2.0)
		{
			// The structure doesn't fit.
			return false;
		}
		
		// Check for occupation conflicts
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{
				if (Terrain::OCCUPIED == t->GetTerrainType(center.y - (cellSize - 2)/2 + i,
														   center.x - (cellSize - 2)/2 + j))
				{
					return false;
				}
			}
		}
		
		// Occupy map cells
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{
				t->Occupy(center.y - (cellSize - 2)/2 + i,
						  center.x - (cellSize - 2)/2 + j);
			}
		}
	}
	else
	{ // Odd
		center = Terrain::GetTerrainPoint(p);  // center in cell coordinates

		// get center in world coordinates for rendering structure
		position = Terrain::GetWorldPoint(center.x, center.y);

		// Check that structure will lie within the world boundaries
		if (position.x - radius < -WIDTH / 2.0 || 
			position.y - radius < -HEIGHT / 2.0 || 
			position.x + radius > WIDTH / 2.0 || 
			position.y + radius > HEIGHT / 2.0)
		{
			// The structure doesn't fit.
			return false;
		}
		
		// Check for occupation conflicts
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{
				if (Terrain::OCCUPIED == t->GetTerrainType(center.y - (cellSize - 1)/2 + i,
														   center.x - (cellSize - 1)/2 + j))
				{
					return false;
				}
			}
		}
		
		// Occupy map cells
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{

				t->Occupy(center.y - (cellSize - 1)/2 + i,
						  center.x - (cellSize - 1)/2 + j);
			}
		}
	}

	return true;
}

void structure::evict(Terrain *t)
{
	// Adjust world coordinates to center the structure
	// on the cell(s) that the user clicked on.
	int cellSize = ceil(2 * radius / (float)STEP);
	vertex center;

	if (0 == cellSize % 2)
	{ // Even
		center = Terrain::GetTerrainPoint(position + AVector(-STEP/2.0, -STEP/2.0));

		// Evict map cells
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{
				t->Evict(center.y - (cellSize - 2)/2 + i,
						 center.x - (cellSize - 2)/2 + j);
			}
		}
	}
	else
	{ // Odd
		center = Terrain::GetTerrainPoint(position);  // center in cell coordinates

		// Occupy map cells
		for (int i = 0; i < cellSize; i++)
		{
			for (int j = 0; j < cellSize; j++)
			{

				t->Evict(center.y - (cellSize - 1)/2 + i,
						 center.x - (cellSize - 1)/2 + j);
			}
		}
	}
}